package com.llu.verifySign;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class DigitalSignatureExample {
    public static void main(String[] args) throws Exception {
        String data = "Hello, World!";

        // 生成RSA密钥对
        KeyPair keyPair = generateRSAKeyPair();

        // 生成数字签名
        String signature = generateDigitalSignature(data, keyPair.getPrivate());
        System.out.println("Signature (Base64): " + signature);

        // 验证数字签名
        boolean isVerified = verifyDigitalSignature(data, signature, keyPair.getPublic());
        System.out.println("Signature Verified: " + isVerified);
    }

    public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 2048位RSA密钥
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 生成数字签名
     *
     * @param data 待签名的数据
     * @param privateKey 用于签名的私钥
     * @return Base64编码的数字签名字符串
     * @throws Exception 如果签名过程中发生错误
     */
    public static String generateDigitalSignature(String data, PrivateKey privateKey) throws Exception {
        // 获取SHA-256和RSA签名实例
        Signature signature = Signature.getInstance("SHA256withRSA");

        // 初始化签名对象
        signature.initSign(privateKey);

        // 更新数据
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        // 生成签名
        byte[] signatureBytes = signature.sign();

        // 将签名字节数组转换为Base64编码字符串
        return Base64.getEncoder().encodeToString(signatureBytes);
    }


    /**
     * 验证数字签名
     *
     * 此方法用于验证给定的数据是否使用指定的公钥和签名算法进行了签名
     * 它使用SHA-256作为哈希算法，RSA作为签名算法
     *
     * @param data 待验证的数据
     * @param signature 待验证的数字签名
     * @param publicKey 用于验证签名的公钥
     * @return 如果签名验证成功，则返回true；否则返回false
     * @throws Exception 如果在验证签名过程中发生错误
     */
    public static boolean verifyDigitalSignature(String data, String signature, PublicKey publicKey) throws Exception {
        // 获取SHA-256和RSA签名实例
        Signature sig = Signature.getInstance("SHA256withRSA");

        // 初始化签名对象
        sig.initVerify(publicKey);

        // 更新数据
        sig.update(data.getBytes(StandardCharsets.UTF_8));

        // 验证签名
        byte[] signatureBytes = Base64.getDecoder().decode(signature);
        return sig.verify(signatureBytes);
    }

}

